package com.jmu.posms.config;

import com.jmu.posms.pojo.Permission;
import com.jmu.posms.service.PermissionService;
import com.jmu.posms.shiro.MyRealm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
@Slf4j
public class ShiroConfig {

    @Resource
    PermissionService permissionService;

    /**
     * 处理拦截资源文件过滤器
     * @param securityManager  shiro安全管理器
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 配置shiro安全管理器 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filters = new HashMap<>();
//        filters.put("authc", new ShiroLoginFilter());
//        filters.put("roles", new ShiroRolesAuthorizationFilter());
//        filters.put("perms", new ShiroPermissionsAuthorizationFilter());

        shiroFilterFactoryBean.setFilters(filters);


        // 指定要求登录时的链接
        shiroFilterFactoryBean.setLoginUrl("/pages/login.html");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/pages/home.html");
        // 未授权时跳转的界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/pages/error.html");



        //设置uri拦截器及的权限控制
        Map<String, String> filterMap = new LinkedHashMap<>();

        //设置权限集合拦截
//        filterMap.put("/user/login","perms[user:login]");
//        filterMap.put("/pages/login.html","perms[user:login]");
//        filterMap.put("/pages/home.html","perms[user:login]");

        List<Permission> permsList = permissionService.list();

        //从数据中读取的url以及权限映射赋值
        for (Permission permission : permsList) {
            filterMap.put(permission.getUrl(),"perms["+permission.getPermissionName()+"]");
        }



//        filterMap.put("/logout","roles[user]");
//        filterMap.put("/register","roles[user]");
//
//        filterMap.put("/**","authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        log.info(filterMap.toString());

        return shiroFilterFactoryBean;
    }

    /**
     * shiro安全管理器
     * @return shiro安全管理器
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();

        // 关联realm
        manager.setRealm(shiroRealm());

        //注入session管理器;
        manager.setSessionManager(sessionManager());
        //注入Cookie记住我管理器
        manager.setRememberMeManager(rememberMeManager());


        return manager;
    }

    @Bean
    public MyRealm shiroRealm() {
        MyRealm realm = new MyRealm();

        //设置hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //设置md5加密
        credentialsMatcher.setHashAlgorithmName("MD5");
        //散列次数
        credentialsMatcher.setHashIterations(1024);
        realm.setCredentialsMatcher(credentialsMatcher);
        return realm;
    }

    /**
     * RememberMe 的功能
     */
    // 创建 Cookie
    @Bean
    public SimpleCookie remeberMeCookie() {
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        // //记住我cookie生效时间30天 ,单位秒  [10天]
        cookie.setMaxAge(864000);
        // 设置只读模型
        //cookie.setHttpOnly(true);
        return cookie;
    }

    /**
     * 配置cookie记住我管理器
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager=new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(remeberMeCookie());
        return cookieRememberMeManager;
    }

    /**
     *
     * 功能描述: sessionManager添加session缓存操作DAO
     *
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

        sessionManager.setSessionDAO(enterCacheSessionDAO());
        sessionManager.setSessionIdCookie(sessionIdCookie());

        return sessionManager;
    }

    /**
     * EnterpriseCacheSessionDAO shiro sessionDao层的实现；
     * 提供了缓存功能的会话维护，默认情况下使用MapCache实现，内部使用ConcurrentHashMap保存缓存的会话。
     */
    @Bean
    public EnterpriseCacheSessionDAO enterCacheSessionDAO() {
        EnterpriseCacheSessionDAO enterCacheSessionDAO = new EnterpriseCacheSessionDAO();
        enterCacheSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
        return enterCacheSessionDAO;
    }


    /**
     *
     * 功能描述: 自定义cookie中session名称等配置
     *
     */
    @Bean
    public SimpleCookie sessionIdCookie() {
        //DefaultSecurityManager
        SimpleCookie simpleCookie = new SimpleCookie();
        //sessionManager.setCacheManager(ehCacheManager());
        //如果在Cookie中设置了"HttpOnly"属性，那么通过程序(JS脚本、Applet等)将无法读取到Cookie信息，这样能有效的防止XSS攻击。
        simpleCookie.setHttpOnly(true);
        simpleCookie.setName("SHRIOSESSIONID");
        //单位秒
        simpleCookie.setMaxAge(86400);
        return simpleCookie;
    }
}
